package mssql

import (
    "fmt"
    "database/sql"
    _ "github.com/denisenkom/go-mssqldb"
    "time"
)

type Conn struct {
    DB  *sql.DB
}

func NewConn(c *Config) (*Conn, error) {
    var dsn string
    if c.Port == 0 {
        c.Port = 1433
    }
    if c.DBName == "" {
        dsn = fmt.Sprintf("server=%s;user id=%s;password=%s;encrypt=disable",
            c.Host,
            c.User,
            c.Password,
        )
    } else {
        dsn = fmt.Sprintf("server=%s;user id=%s;password=%s;database=%s;encrypt=disable",
            c.Host,
            c.User,
            c.Password,
            c.DBName,
        )
    }

    if db, err := sql.Open("mssql", dsn); err != nil {
        return nil, err
    } else if err := db.Ping(); err != nil {
        return nil, err
    } else {
        db.SetConnMaxLifetime(10 * time.Minute)
        db.SetMaxIdleConns(10)
        db.SetMaxOpenConns(100)
        return &Conn{DB: db}, nil
    }
}

func (this *Conn) Exec(sql string, args ...interface{}) (int, error) {
    res, err := this.DB.Exec(sql, args...)
    if err != nil {
        return 0, err
    }
    var row int64
    row, err = res.LastInsertId()
    if err != nil {
        return 0, err
    }
    if row == 0 {
        row, _ = res.RowsAffected()
    }
    return int(row), nil
}

func (this *Conn) Query(sql string, args ...interface{}) (Values, error) {
    rows, err := this.DB.Query(sql, args...)
    defer func() {
        if rows != nil {
            rows.Close()
        }
    }()
    if err != nil {
        return nil, err
    }
    ary, err := RowsToAry(rows)
    return ary, nil
}